/**
 * 懒加载工具
 */

// 懒加载配置
interface LazyLoadOptions {
  root?: Element | null
  rootMargin?: string
  threshold?: number | number[]
  once?: boolean
}

// 懒加载回调函数
type LazyLoadCallback = (entry: IntersectionObserverEntry) => void

class LazyLoader {
  private observer: IntersectionObserver | null = null
  private callbacks = new Map<Element, LazyLoadCallback>()

  constructor(options: LazyLoadOptions = {}) {
    if (typeof window === 'undefined') return

    const defaultOptions: IntersectionObserverInit = {
      root: options.root || null,
      rootMargin: options.rootMargin || '50px',
      threshold: options.threshold || 0.1
    }

    this.observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        const callback = this.callbacks.get(entry.target)
        if (callback) {
          callback(entry)
          
          // 如果设置了只执行一次，则停止观察
          if (options.once && entry.isIntersecting) {
            this.unobserve(entry.target)
          }
        }
      })
    }, defaultOptions)
  }

  /**
   * 观察元素
   */
  observe(element: Element, callback: LazyLoadCallback) {
    if (!this.observer) return

    this.callbacks.set(element, callback)
    this.observer.observe(element)
  }

  /**
   * 停止观察元素
   */
  unobserve(element: Element) {
    if (!this.observer) return

    this.observer.unobserve(element)
    this.callbacks.delete(element)
  }

  /**
   * 销毁观察器
   */
  destroy() {
    if (this.observer) {
      this.observer.disconnect()
      this.observer = null
    }
    this.callbacks.clear()
  }
}

// 创建全局懒加载器
export const lazyLoader = new LazyLoader()

/**
 * 图片懒加载
 */
export const lazyLoadImage = (img: HTMLImageElement, src: string, placeholder?: string) => {
  if (placeholder) {
    img.src = placeholder
  }

  lazyLoader.observe(img, (entry) => {
    if (entry.isIntersecting) {
      img.src = src
      img.classList.add('loaded')
    }
  })
}

/**
 * 组件懒加载
 */
export const lazyLoadComponent = (element: Element, callback: () => void) => {
  lazyLoader.observe(element, (entry) => {
    if (entry.isIntersecting) {
      callback()
    }
  })
}

/**
 * 路由懒加载
 */
export const lazyLoadRoute = (importFn: () => Promise<any>) => {
  return () => importFn()
}

/**
 * 预加载资源
 */
export const preloadResource = (href: string, as: string = 'script') => {
  const link = document.createElement('link')
  link.rel = 'preload'
  link.href = href
  link.as = as
  document.head.appendChild(link)
}

/**
 * 预连接域名
 */
export const preconnectDomain = (href: string) => {
  const link = document.createElement('link')
  link.rel = 'preconnect'
  link.href = href
  document.head.appendChild(link)
}

/**
 * 预获取资源
 */
export const prefetchResource = (href: string) => {
  const link = document.createElement('link')
  link.rel = 'prefetch'
  link.href = href
  document.head.appendChild(link)
}

/**
 * 销毁懒加载器
 */
export const destroyLazyLoader = () => {
  lazyLoader.destroy()
}
